package org.aplikator.server.descriptor;

import static org.aplikator.server.descriptor.Panel.row;

import org.aplikator.client.descriptor.ReferenceFieldDTO;
import org.aplikator.client.descriptor.WidgetDTO;
import org.aplikator.server.Context;

public class ReferenceField<T extends Entity> implements Widget, HasProperty<Integer> {

    private Reference<T> property;
    private View view;
    private Widget child;

    public ReferenceField(Reference<T> property, View view, Widget child) {
        this.property = property;
        this.view = view;
        this.child = child;
    }

    public Reference<T> getProperty() {
        return property;
    }

    public WidgetDTO getWidgetDescriptor(Context ctx) {
        ReferenceFieldDTO desc = new ReferenceFieldDTO(property.clientClone(ctx), view.getViewDTO(ctx), child.getWidgetDescriptor(ctx));
        return desc;
    }

    public void registerProperties(Form form) {
        form.addProperty(property);
        child.registerProperties(form);
    }

    public static <T extends Entity> ReferenceField<T> reference(Reference<T> property, View view, Widget child){
        return new ReferenceField<T>(property, view, child);
    }

    public static <T extends Entity> ReferenceField<T> reference(Reference<T> property,  Widget child){
        return reference(property, property.referredEntity.view(), child);
    }

    public static <T extends Entity> ReferenceField<T> reference(Reference<T> property){
        return reference(property, property.referredEntity.view(), property.referredEntity.view().getForm(null).getLayout());
    }


    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static <T extends Entity> ReferenceField<T> reference(Reference<T> property, View view, Property<?>... children){
        Panel panel = row();
        for (Property<?> p : children){
            panel.add(new LabelField(property.relate(p)));
        }
        return reference(property, view, panel);
    }

    public static <T extends Entity> ReferenceField<T> reference(Reference<T> property,  Property<?>... children){
        return reference(property,property.referredEntity.view(), children);
    }
}
